package net.pws.oos.biz.service.impl;

import java.text.MessageFormat;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;

import net.pws.common.beanutils.BeanUtils;
import net.pws.common.persistence.EntityManager;
import net.pws.oos.biz.BizException;
import net.pws.oos.biz.EntityUtils;
import net.pws.oos.biz.exception.InvalidPasswordException;
import net.pws.oos.biz.model.Indicator;
import net.pws.oos.biz.model.IndicatorValue;
import net.pws.oos.biz.model.OperateLog;
import net.pws.oos.biz.query.IndicatorFinder;
import net.pws.oos.biz.query.parameter.IndicatorValueQueryParameter;
import net.pws.oos.biz.service.IndicatorService;

import org.apache.commons.lang.BooleanUtils;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

@Service(value = "indicatorService")
@Transactional
@SuppressWarnings({ "rawtypes", "unchecked" })
public class DefaultIndicatorManageService implements IndicatorService {

	@Autowired
	private EntityManager entityManager;

	@Autowired
	private IndicatorFinder indicatorFinder;

//	@Autowired
//	private PasswordEncoder passwordEncoder;

	public IndicatorValue saveIndicatorValue(IndicatorValue indicatorValue) {
		if (StringUtils.isEmpty(indicatorValue.getId())) {
//			// verify lcs
//			Licence lcs = LicenceFactory.getInstance().getLicence();
//			if (lcs.getIndicatorValueLimit() > 0) {
//				int count = ((Number) entityManager.findUnique(
//						"select count(u.id) from IndicatorValue u where u.deleted = ?",
//						new Object[] { Boolean.FALSE })).intValue();
//				if (count >= lcs.getIndicatorValueLimit()) {
//					throw new BizException(Licence.MSG_USER);
//				}
//			}

			int count = ((Number) entityManager.findUnique(
					"select count(u.id) from IndicatorValue u where u.name = ? and u.indicator.id = ? ",
					new Object[] { indicatorValue.getName(),indicatorValue.getIndicator().getId() })).intValue();
			if (count > 0) {
				throw new BizException(MessageFormat.format("指标值[{0}]重复",
						indicatorValue.getName()));
			}


		} else {
			int count = ((Number) entityManager
					.findUnique(
							"select count(u.id) from IndicatorValue u where u.name = ? and u.id != ?",
							new Object[] { indicatorValue.getName(), indicatorValue.getId() }))
					.intValue();
			if (count > 0) {
				throw new BizException(MessageFormat.format("指标值[{0}]重复",
						indicatorValue.getName()));
			}
		}

		entityManager.persist(indicatorValue);
		return indicatorValue;
	}

	public void deleteIndicatorValue(String id) {
		IndicatorValue indicatorValue = entityManager.find(IndicatorValue.class, id);
		if (null == indicatorValue) {
			return;
		}

		indicatorValue.setDeleted(Boolean.TRUE);
		String name = indicatorValue.getName();
		if (name.length() > 46) {
			name = name.substring(0, 46);
		}
		indicatorValue.setName(name + "|已删除");

//		indicatorValue.setIndicator(null);
		entityManager.persist(indicatorValue);

	}

	public void changeIndicatorValuePassword(String indicatorValueId, String newPassword) {
		if (StringUtils.isEmpty(newPassword)) {
			throw new InvalidPasswordException("指标值密码不能为空！");
		}
		IndicatorValue indicatorValue = entityManager.find(IndicatorValue.class, indicatorValueId);
//		if (null == indicatorValue) {
//			throw new IndicatorValueNotFoundException(MessageFormat.format(
//					"无效的指标值[id={0}]", indicatorValueId));
//		}

//		String encodedPassword = encodePassword(newPassword);
//		indicatorValue.setPassword(encodedPassword);
		entityManager.persist(indicatorValue);
	}

	public void changeIndicatorValuePassword(String indicatorValueId, String oldPassword,
			String newPassword) {
		if (StringUtils.isEmpty(oldPassword)
				|| StringUtils.isEmpty(newPassword)) {
			throw new InvalidPasswordException("指标值密码不能为空！");
		}
		IndicatorValue indicatorValue = entityManager.find(IndicatorValue.class, indicatorValueId);
//		if (null == indicatorValue) {
//			throw new IndicatorValueNotFoundException(MessageFormat.format(
//					"无效的指标值[id={0}]", indicatorValueId));
//		}
//
//		String encodedOldPassword = encodePassword(oldPassword);
//		if (!encodedOldPassword.equals(indicatorValue.getPassword())) {
//			throw new InvalidPasswordException("输入的旧密码不正确！");
//		}
//		String encodedNewPassword = encodePassword(newPassword);
//		indicatorValue.setPassword(encodedNewPassword);
		entityManager.persist(indicatorValue);
	}

	// bind
//	@Transactional
//	public void bindIndicatorValueRole(String indicatorValueId, String[] roleIds) {
//		UnitOfWork unitOfWork = new UnitOfWork();
//		IndicatorValue indicatorValue = entityManager.find(IndicatorValue.class, indicatorValueId);
//		for (int i = 0; i < roleIds.length; i++) {
//			Role role = entityManager.find(Role.class, roleIds[i]);
//			indicatorValue.getRoles().add(role);
//			role.getIndicatorValues().add(indicatorValue);
//			unitOfWork.registerDirty(role);
//		}
//		unitOfWork.registerDirty(indicatorValue);
//		entityManager.execute(unitOfWork);
//
//		ApplicationEventBus.getInstance().publishEvent(
//				new PermissionChangedEventObject(indicatorValueId,
//						PermissionChangedType.USER_CHANGED));
//	}
//
//	public void unbindIndicatorValueRole(String indicatorValueId, String[] roleIds) {
//		UnitOfWork unitOfWork = new UnitOfWork();
//		IndicatorValue indicatorValue = entityManager.find(IndicatorValue.class, indicatorValueId);
//		for (int i = 0; i < roleIds.length; i++) {
//			Role role = entityManager.find(Role.class, roleIds[i]);
//			indicatorValue.getRoles().remove(role);
//			role.getIndicatorValues().remove(indicatorValue);
//			unitOfWork.registerDirty(role);
//		}
//		unitOfWork.registerDirty(indicatorValue);
//		entityManager.execute(unitOfWork);
//
//		ApplicationEventBus.getInstance().publishEvent(
//				new PermissionChangedEventObject(indicatorValueId,
//						PermissionChangedType.USER_CHANGED));
//
//	}
//
//	public void bindRoleIndicatorValue(String roleId, String[] indicatorValueIds) {
//		UnitOfWork unitOfWork = new UnitOfWork();
//		Role role = entityManager.find(Role.class, roleId);
//		for (int i = 0; i < indicatorValueIds.length; i++) {
//			IndicatorValue indicatorValue = entityManager.find(IndicatorValue.class, indicatorValueIds[i]);
//			indicatorValue.getRoles().add(role);
//			role.getIndicatorValues().add(indicatorValue);
//			unitOfWork.registerDirty(indicatorValue);
//		}
//		unitOfWork.registerDirty(role);
//		entityManager.execute(unitOfWork);
//
//		ApplicationEventBus.getInstance().publishEvent(
//				new PermissionChangedEventObject(roleId,
//						PermissionChangedType.ROLE_CHANGED));
//	}
//
//	public void unbindRoleIndicatorValue(String roleId, String[] indicatorValueIds) {
//		UnitOfWork unitOfWork = new UnitOfWork();
//		Role role = entityManager.find(Role.class, roleId);
//		for (int i = 0; i < indicatorValueIds.length; i++) {
//			IndicatorValue indicatorValue = entityManager.find(IndicatorValue.class, indicatorValueIds[i]);
//			indicatorValue.getRoles().remove(role);
//			role.getIndicatorValues().remove(indicatorValue);
//			unitOfWork.registerDirty(indicatorValue);
//		}
//		unitOfWork.registerDirty(role);
//		entityManager.execute(unitOfWork);
//
//		ApplicationEventBus.getInstance().publishEvent(
//				new PermissionChangedEventObject(roleId,
//						PermissionChangedType.ROLE_CHANGED));
//	}
//
//	public Role saveRole(Role role) {
//		if (StringUtils.isEmpty(role.getId())) {
//			int count = ((Number) entityManager.findUnique(
//					"select count(u.id) from Role u where u.name = ?",
//					new Object[] { role.getName() })).intValue();
//			if (count > 0) {
//				throw new BizException(MessageFormat.format("名称[{0}]重复",
//						role.getName()));
//			}
//			count = ((Number) entityManager.findUnique(
//					"select count(u.id) from Role u where u.code = ?",
//					new Object[] { role.getCode() })).intValue();
//			if (count > 0) {
//				throw new BizException(MessageFormat.format("编码[{0}]重复",
//						role.getCode()));
//			}
//
//		} else {
//			int count = ((Number) entityManager
//					.findUnique(
//							"select count(u.id) from Role u where u.name = ? and u.id != ?",
//							new Object[] { role.getName(), role.getId() }))
//					.intValue();
//			if (count > 0) {
//				throw new BizException(MessageFormat.format("名称[{0}]重复",
//						role.getName()));
//			}
//			count = ((Number) entityManager
//					.findUnique(
//							"select count(u.id) from Role u where u.code = ? and u.id != ?",
//							new Object[] { role.getCode(), role.getId() }))
//					.intValue();
//			if (count > 0) {
//				throw new BizException(MessageFormat.format("编码[{0}]重复",
//						role.getCode()));
//			}
//		}
//
//		entityManager.persist(role);
//		return role;
//	}
//
//	public void deleteRole(String id) {
//		Role role = entityManager.find(Role.class, id);
//		if (null == role) {
//			return;
//		}
//
//		entityManager.nativeExecute(
//				"delete from s_permission where role_id = ? ",
//				new Object[] { id });
//		entityManager.nativeExecute(
//				"delete from s_indicatorValue_role where role_id = ? ",
//				new Object[] { id });
//		entityManager.nativeExecute("delete from s_role where id = ? ",
//				new Object[] { id });
//	}
//
//	public void deleteRole(String[] ids) {
//		StringBuffer sb = new StringBuffer("(");
//		for (int i = 0; i < ids.length; i++) {
//			if (i > 0) {
//				sb.append(",");
//			}
//			sb.append("?");
//		}
//		sb.append(")");
//		entityManager.nativeExecute(
//				"delete from s_permission where role_id in " + sb.toString(),
//				ids);
//		entityManager.nativeExecute("delete from s_indicatorValue_role where role_id in "
//				+ sb.toString(), ids);
//		entityManager.nativeExecute(
//				"delete from s_role where id in " + sb.toString(), ids);
//	}

	public Indicator saveIndicator(Indicator indicator) {
		if (StringUtils.isEmpty(indicator.getId())) {
			if (indicator.getParent() == null) {
//				throw new BizException("不能新建顶级指标项！");
			}

			int count = ((Number) entityManager.findUnique(
					"select count(u.id) from Indicator u where u.deleted = false and u.name = ? and u.depth = ?",
					new Object[] { indicator.getName(),indicator.getDepth() })).intValue();
			if (count > 0) {
				throw new BizException(MessageFormat.format("名称[{0}]重复", indicator.getName()));
			}
//			count = ((Number) entityManager
//					.findUnique(
//							"select count(u.id) from Indicator u where u.shortName = ?",
//							new Object[] { indicator.getShortName() }))
//					.intValue();
//			if (count > 0) {
//				throw new BizException(MessageFormat.format("简称[{0}]重复",
//						indicator.getShortName()));
//			}

//			count = ((Number) entityManager.findUnique(
//					"select count(u.id) from Indicator u where u.code = ?",
//					new Object[] { indicator.getCode() })).intValue();
//			if (count > 0) {
//				throw new BizException(MessageFormat.format("编码[{0}]重复",
//						indicator.getCode()));
//			}
			newInheritance(indicator);
		} else {
			int count = ((Number) entityManager
					.findUnique(
							"select count(u.id) from Indicator u where u.name = ? and u.id != ? and u.depth = ? ",
							new Object[] { indicator.getName(),
									indicator.getId(), indicator.getDepth()})).intValue();
			if (count > 0) {
				throw new BizException(MessageFormat.format("名称[{0}]重复",
						indicator.getName()));
			}
			count = ((Number) entityManager
					.findUnique(
							"select count(u.id) from Indicator u where u.shortName = ? and u.id != ? and u.depth = ?",
							new Object[] { indicator.getShortName(),
									indicator.getId(), indicator.getDepth()})).intValue();
			if (count > 0) {
				throw new BizException(MessageFormat.format("简称[{0}]重复",
						indicator.getShortName()));
			}
			count = ((Number) entityManager
					.findUnique(
							"select count(u.id) from Indicator u where u.code = ? and u.id != ? and u.depth = ? ",
							new Object[] { indicator.getCode(),
									indicator.getId(), indicator.getDepth()})).intValue();
			if (count > 0) {
				throw new BizException(MessageFormat.format("编码[{0}]重复",
						indicator.getCode()));
			}
			indicator = updateInheritance(indicator);
		}

		entityManager.persist(indicator);
		return indicator;
	}

	/**
	 * 更新指标项时更新树型关系
	 * 
	 * @param indicator
	 * @return 返回修改属性的指标项
	 */
	private Indicator updateInheritance(Indicator indicator) {
		Indicator parent = indicator.getParent();
		Indicator oldIndicator = indicatorFinder.getIndicator(indicator.getId());
		if (oldIndicator == null) {
			throw new BizException(MessageFormat.format("要修改的指标项[{0}]不存在！", indicator.getName()));
		}
		Indicator oldParent = oldIndicator.getParent();

		if (parent != null
				&& (parent.getId().equals(indicator.getId()) || EntityUtils
						.isSubInnerCode(oldIndicator.getInnerCode(),
								oldIndicator.getDepth(), parent.getInnerCode()))) {
			throw new BizException(MessageFormat.format(
					"要修改的指标项[{0}]的上级不能是自己或下级！", indicator.getName()));
		}

		if (EntityUtils.isEqual(parent, oldParent)) { // 未修改父节点
			indicator.setDepth(oldIndicator.getDepth());
			indicator.setInnerCode(oldIndicator.getInnerCode());
			BeanUtils.copyProperties(oldIndicator, indicator);
		} else { // 修改了父节点
			indicator.setDepth(parent == null ? 0 : parent.getDepth() + 1);
			indicator.setInnerCode(computeInnerCode(parent));
			BeanUtils.copyProperties(oldIndicator, indicator);

			// 更新原父节点
			if (oldParent != null && oldParent.getChildren().size() <= 1) {
				oldParent.setLeaf(true);
				entityManager.persist(oldParent);
			}

			// 更新新父节点
			if (parent != null && parent.isLeaf()) {
				parent.setLeaf(false);
				entityManager.persist(parent);
			}

			// 更新子节点
			updateChildrenInnerCode(oldIndicator);
		}

		return oldIndicator;
	}

	/**
	 * 更新子节点编码与深度
	 * 
	 * @param parent 父节点
	 * 
	 */
	private void updateChildrenInnerCode(Indicator parent) {
		List<Indicator> children = entityManager.findList(
				"from Indicator o where o.parent.id = ?",
				new Object[] { parent.getId() });

		for (Indicator child : children) {
			String subCode = EntityUtils.updateInnerCode(parent.getInnerCode(),
					parent.getDepth(), child.getInnerCode(), child.getDepth());
			child.setInnerCode(subCode);
			child.setDepth(parent.getDepth() + 1);
			entityManager.persist(child);

			// 更新下级子
			updateChildrenInnerCode(child);
		}
	}

	/**
	 * 新增指标项时更新树形的关系
	 * 
	 * @param indicator
	 */
	private void newInheritance(Indicator indicator) {
		// 更新父节点
		Indicator parent = indicator.getParent();
		if (parent != null && parent.isLeaf()) {
			parent.setLeaf(false);
			entityManager.persist(parent);
		}

		indicator.setDepth(parent == null ? 0 : parent.getDepth() + 1);
		indicator.setInnerCode(computeInnerCode(parent));
	}

	/**
	 * 根据父节点，得到当前节点的编码
	 * 
	 * @param parent
	 * @return
	 */
	private String computeInnerCode(Indicator parent) {
		if (parent == null) {
			Indicator littleBrother = getMaxCodeIndicator(null);
			if (littleBrother == null) {
				return EntityUtils.newInnerCode(null, 0);
			} else {
				return EntityUtils.plusInnerCode(littleBrother.getInnerCode(),
						littleBrother.getDepth());
			}
		} else {
			Indicator littleBrother = getMaxCodeIndicator(parent.getId());
			if (littleBrother == null) {
				return EntityUtils.newInnerCode(parent.getInnerCode(),
						parent.getDepth() + 1);
			} else {
				return EntityUtils.plusInnerCode(littleBrother.getInnerCode(),
						littleBrother.getDepth());
			}
		}
	}

	/**
	 * 得到指定机构的子中内部编码最大的
	 * 
	 * @param parentId
	 * @return
	 */
	private Indicator getMaxCodeIndicator(String parentId) {
		List<Object> params = new ArrayList<Object>();
		StringBuilder hql = new StringBuilder("from Indicator where ");
		if (StringUtils.isEmpty(parentId)) {
			hql.append(" parent is null ");
		} else {
			hql.append(" parent.id=? ");
			params.add(parentId);
		}
		hql.append(" order by innerCode desc ");
		return (Indicator) entityManager.findFirst(hql.toString(),
				params.toArray());
	}

	public void deleteIndicator(String id) {
		Indicator indicator = entityManager.find(Indicator.class, id);
		if (null == indicator) {
			return;
		}

		// 判断是否有下级指标项
		Set<Indicator> children = indicator.getChildren();
		for (Indicator child : children) {
			if (!BooleanUtils.isTrue(child.getDeleted())) {
				throw new BizException("该指标项下面包含有下级指标项，不能删除！或者请将下级指标项删除后再继续本操作！");
			}
		}

		// 判断是否有指标值
		IndicatorValueQueryParameter queryParameter = new IndicatorValueQueryParameter();
		queryParameter.setIndicatorId(indicator.getId());
		if (indicatorFinder.countIndicatorValue(queryParameter) > 0) {
			throw new BizException("该指标项下面包含有指标值，不能删除！或者请将相关指标值删除后再继续本操作！");
		}

		// 更新父节点
		Indicator parent = indicator.getParent();
		if (parent.getChildren().size() <= 1) {
			parent.setLeaf(true);
			entityManager.persist(parent);
		}

		String name = indicator.getName();
		if (name.length() > 46) {
			name = name.substring(0, 46);
		}
		indicator.setName(name + "|已删除");
		String code = indicator.getCode();
		if (code.length() > 46) {
			code = code.substring(0, 46);
		}
		indicator.setCode(code + "|已删除");
//		indicator.setParent(null);
		indicator.setInnerCode("");
		indicator.setDeleted(Boolean.TRUE);
		entityManager.persist(indicator);
	}

//	// resource
//	public int getResourceCount() {
//		return ResourceDefinitionRepository.getInstance().resourceCount();
//	}
//
//	public List<Resource> getResourceChildren(String id) {
//		if (StringUtils.isEmpty(id)) {
//			return Arrays.asList(ResourceDefinitionRepository.getInstance()
//					.getResources());
//		}
//		return Arrays.asList(ResourceDefinitionRepository.getInstance()
//				.getResourceChildren(id));
//	}
//
//	public List<Resource> getResourceList() {
//		return Arrays.asList(ResourceDefinitionRepository.getInstance()
//				.getAllResources());
//	}
//
//	public Resource getResource(String id) {
//		return ResourceDefinitionRepository.getInstance().getResource(id);
//	}

//	public List<Map> getMenuPermissionChildren(String id, String roleId) {
//		List<Permission> permissions = entityManager.findList(
//				" from Permission p where p.role.id = ?",
//				new Object[] { roleId });
//		if (StringUtils.isEmpty(id)) {
//			Resource[] resources = ResourceDefinitionRepository.getInstance()
//					.getResources(IResource.MENU);
//
//			return mergeMenuAndPermission(resources, permissions);
//		}
//
//		Resource[] resources = ResourceDefinitionRepository.getInstance()
//				.getResourceChildren(id, IResource.MENU);
//		return mergeMenuAndPermission(resources, permissions);
//	}
//
//	public List<Map> getMenuOperationPermissionChildren(String id, String roleId) {
//		List<Permission> permissions = entityManager.findList(
//				" from Permission p where p.role.id = ?",
//				new Object[] { roleId });
//		if (StringUtils.isEmpty(id)) {
//			Resource[] resources = ResourceDefinitionRepository.getInstance()
//					.getResources(IResource.MENU);
//			return mergeMenuAndPermission(resources, permissions);
//		}
//
//		Resource[] resources = ResourceDefinitionRepository.getInstance()
//				.getResourceChildren(id);
//		return mergeMenuAndPermission(resources, permissions);
//	}
//
//	private List<Map> mergeMenuAndPermission(Resource[] resources,
//			List<Permission> permissions) {
//		Map<String, Permission> permissionMap = new HashMap<String, Permission>();
//		for (Permission permission : permissions) {
//			permissionMap.put(permission.getResourceId(), permission);
//		}
//
//		List<Map> result = new ArrayList<Map>();
//		for (Resource resource : resources) {
//			Map item = new HashMap();
//
//			item.put("id", resource.getId());
//			item.put("name", resource.getName());
//			Permission permission = permissionMap.get(resource.getId());
//			if (null != permission) {
//				item.put("permissionId", permission.getId());
//			}
//
//			result.add(item);
//		}
//		return result;
//	}
//
//	public List saveMenuPermission(String roleId, List menuPermissions) {
//		List result = new ArrayList();
//		boolean permissionChanged = false;
//		for (Iterator iterator = menuPermissions.iterator(); iterator.hasNext();) {
//			Map menuPermission = (Map) iterator.next();
//			String resourceId = (String) menuPermission.get("id");
//			String permissionId = (String) menuPermission.get("permissionId");
//			Boolean checked = (Boolean) menuPermission.get("checked");
//			if (BooleanUtils.isTrue(checked)
//					&& StringUtils.isEmpty(permissionId)) {
//				Permission permission = new Permission();
//				permission.setRole(entityManager.getReference(Role.class,
//						roleId));
//				permission.setResourceId(resourceId);
//				entityManager.persist(permission);
//
//				Map item = new HashMap();
//				item.put("id", resourceId);
//				item.put("permissionId", permission.getId());
//				result.add(item);
//
//				permissionChanged = true;
//			} else if (BooleanUtils.isFalse(checked)
//					&& StringUtils.isNotEmpty(permissionId)) {
//				entityManager.removeById(Permission.class, permissionId);
//
//				Map item = new HashMap();
//				item.put("id", resourceId);
//				item.put("permissionId", null);
//				result.add(item);
//
//				permissionChanged = true;
//			}
//		}
//		if (permissionChanged) {
//			ApplicationEventBus.getInstance().publishEvent(
//					new PermissionChangedEventObject(roleId,
//							PermissionChangedType.ROLE_CHANGED));
//		}
//		return result;
//	}

	@Transactional(propagation = Propagation.REQUIRES_NEW)
	public void saveOperateLog(OperateLog operateLog) {
		entityManager.save(operateLog);
	}

//	private String encodePassword(String password) {
//		if (passwordEncoder == null) {
//			return password;
//		}
//		return passwordEncoder.encode(password);
//	}

}
